/*
 * Copyright (C) 2008 aki@akjava.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.akjava.android.openglsamples.glut;

import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.opengles.GL10;

import android.app.Activity;
import android.content.Context;
import android.os.SystemClock;
import android.util.Log;
import android.view.KeyEvent;

import com.akjava.android.openglsamples.GLUT;
import com.akjava.android.openglsamples.GLView;
import com.akjava.android.openglsamples.OpenGLUtils;
import com.akjava.android.openglsamples.GLView.EventListener;
import com.akjava.android.openglsamples.GLView.FpsPrinter;

public  class GLUTSimpleRenderer implements GLView.Renderer,EventListener,FpsPrinter{

	public static final int BOX=0;
	public static final int CUBE=1;
	public static final int TORUS=2;
	public static final int SPHERE=3;
	public static final int CONE=4;
	public static final int TEAPOT=5;
	int mode;
    public GLUTSimpleRenderer(Activity context) {
        mContext = context;
        initialize();
        setFpsPrinter(this);
    }

    
    
    public int[] getConfigSpec() {

        int[] configSpec = {
        		 EGL10.EGL_RED_SIZE,      5,
                 EGL10.EGL_GREEN_SIZE,    6,
                 EGL10.EGL_BLUE_SIZE,     5,
                 EGL10.EGL_DEPTH_SIZE,   16,
                 EGL10.EGL_NONE
        };
        return configSpec;
    }


    public void displayObjects(GL10 gl) {

    	gl.glRotatef (45.0f, 0.0f, 0.0f, 1.0f);
  	    gl.glRotatef (45.0f, 1.0f, 0.0f, 0.0f);
  	  
  	    if(mode==BOX){
  	    	if(wireFrame){
  	      	GLUT.glutWireBox(gl, 1f, 1.5f, 3);	
  	      	}else{
  	      	GLUT.glutSolidBox(gl, 1f, 1.5f, 3);
  	      	}
  	    }
  	    else if(mode==CUBE){
  	  	if(wireFrame){
  	    	GLUT.glutWireCube(gl,2.5f);	
  	    	}else{
  	    	GLUT.glutSolidCube(gl, 2.5f);
  	    	}
  	    }  else if(mode==TORUS){
  	  	  	if(wireFrame){
  	  	  	    GLUT.glutWireTorus(gl,0.275f, 0.85f, 12, 12);
  	  	    	}else{
  	  	    	 GLUT.glutSolidTorus(gl,0.275f, 0.85f, 12, 12);
  	  	    	}
  	  	    }else if(mode==SPHERE){
  	  	  	  	if(wireFrame){
  	  	  	  	    GLUT.glutWireSphere(gl, 2, 12, 12);
  	  	  	    	}else{
  	  	  	    	GLUT.glutSolidSphere(gl, 2, 12, 12);
  	  	  	    	}
  	  	  	    }else if(mode==CONE){
  	  	  	  gl.glDisable(GL10.GL_CULL_FACE);	//cone need
  	  	  	  	  	if(wireFrame){
  	  	  	  	  	    GLUT.glutWireCone(gl, 2,2, 12, 12);
  	  	  	  	    	}else{
  	  	  	  	    GLUT.glutSolidCone(gl, 2,2, 12, 12);
  	  	  	  
  	  	  	  	    	}
  	  	  	  	    }else if(mode==TEAPOT){
  	  	  	  	  	  gl.glDisable(GL10.GL_CULL_FACE);	//cone need
    	  	  	  	  	if(wireFrame){
    	  	  	  	  	    GLUT.glutSolidTeapot(gl, 8f);
    	  	  	  	    	}else{
    	  	  	  	    	GLUT.glutSolidTeapot(gl, 8f);
    	  	  	  
    	  	  	  	    	}
    	  	  	  	    }
    	
    }


    private void showFps(){
    	
    	long t=SystemClock.uptimeMillis();
    	if(lastDraw!=0){
    	
    	int diff=(int)(t-lastDraw);
    	if(diff>0){
    		double fps=1000.0/diff;
    		String label=""+fps;
    		int l=label.indexOf(".");
    		if(l!=-1){
    			label=label.substring(0,l+2);
    		}
    		if(printer!=null){
    		printer.showFps(label);
    		}
    	}
    	}
    	lastDraw=t;
    }

    long lastDraw;
    public void display(GL10 gl) {
    	 //someway need 
    	showFps();
    	
   	    gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
        //GLU.gluLookAt(gl, 0, 0, 7f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
        gl.glEnable(GL10.GL_CULL_FACE);	//especiall box need it.
       
        
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        //move
        gl.glRotatef(rightLeftValue, 0, 1f, 0);
  	    gl.glRotatef(topDownValue, 1f, 0, 0);
        displayObjects(gl);
    }

    


	public void init(GL10 gl) {
		float mat_ambient[] = { 1.0f, 1.0f, 1.0f, 1.0f};
		float mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
		float light_position[] = { 0.0f, 0.0f, 10.0f, 1.0f };
		//float lm_ambient[] = { 0.2f, 0.2f, 0.2f, 1.0f };
		float lm_ambient[] = { 0.2f, 0.2f, 0.2f, 1.0f };
		float lm_diffuse[] = new float[] { 1f, 1f, 1f, 1.0f };
		   gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, mat_ambient,0);	//GL_FRONT is wrong?
		   gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_SPECULAR,mat_specular,0);
		   gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, cube_diffuseBuffer);
		   gl.glMaterialf(GL10.GL_FRONT_AND_BACK, GL10.GL_SHININESS, 50.0f);
		   gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, OpenGLUtils.toFloatBufferPositionZero(light_position));
		   //gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, OpenGLUtils.toFloatBuffer(lm_ambient));
		   gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, OpenGLUtils.toFloatBufferPositionZero(lm_diffuse));
		   gl.glLightModelfv(GL10.GL_LIGHT_MODEL_AMBIENT, OpenGLUtils.toFloatBufferPositionZero(lm_ambient));

		   gl.glEnable(GL10.GL_LIGHTING);
		   gl.glEnable(GL10.GL_LIGHT0);
		   gl.glEnable(GL10.GL_DEPTH_TEST);
		   gl.glShadeModel (GL10.GL_FLAT);

		   gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
 	  
		   gl.glDepthFunc(GL10.GL_LEQUAL);
		   gl.glClearDepthf(1.0f);
	}
	
	int[] vPort = new int[4];
    public void sizeChanged(GL10 gl, int w, int h) {
    	
    		vPort[2]=w;
    		vPort[3]=h;
    	
    	   gl.glViewport(0, 0, w, h);
    	   gl.glMatrixMode(GL10.GL_PROJECTION);
    	   gl.glLoadIdentity();
    	   
    	   if (w <= h) 
    	      gl.glOrthof(-2.25f, 2.25f, 
    	         -2.25f*(float)h/(float)w, 2.25f*(float)h/(float)w,-10,10);
    	   else 
    		   gl.glOrthof (-2.25f*(float)w/(float)h, 
    	    		  2.25f*(float)w/(float)h, -2.25f, 2.25f,-10,10);
    	   gl.glMatrixMode(GL10.GL_MODELVIEW);
    	   gl.glLoadIdentity();
    	   
        
    }
    

    public void initialize() {
        mFVertexBuffer = OpenGLUtils.allocateFloatBuffer(1000);
        mColorBuffer = OpenGLUtils.allocateFloatBuffer(1000);
        mIndexBuffer = OpenGLUtils.allocateShortBuffer(1000);
        
        
        OpenGLUtils.addVertex3f(mFVertexBuffer, -0.5f	,0.5f, 0);
        OpenGLUtils.addVertex3f(mFVertexBuffer, 0.5f	,-0.5f, 0);
        
        OpenGLUtils.addVertex3f(mFVertexBuffer, 0.5f	,0.5f, 0);
        OpenGLUtils.addVertex3f(mFVertexBuffer, -0.5f	,-0.5f, 0);

        
       float cube_diffuse[] = { 0.0f, 0.7f, 0.7f, 1.0f };
   	   
   	   cube_diffuseBuffer=OpenGLUtils.toFloatBufferPositionZero(cube_diffuse);
        
        mFVertexBuffer.position(0);
        mColorBuffer.position(0);
        mIndexBuffer.position(0);
        

    }

    
    private FloatBuffer cube_diffuseBuffer;
    public void surfaceCreated(GL10 gl) {
    	 init(gl);
    }

    public void drawFrame(GL10 gl) {
        
        display(gl);
    }

  

    public Context getContext(){
    	return mContext;
    }
    protected Context mContext;
    protected FloatBuffer mFVertexBuffer;
    protected FloatBuffer mColorBuffer;
    protected ShortBuffer mIndexBuffer;
    


    

    public boolean onKeyDown(int keyCode, KeyEvent event) {
    	
    	if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
    		actionUp();
    	}else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
    	  actionDown();
    	}
    		if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
    			actionRight();
    		}else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
    			actionLeft();
    	}else if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
    		actionCenter();
    	}else if (keyCode == KeyEvent.KEYCODE_SPACE) {
    		
    	}
    	return true;
    }
    
   protected int xChange=10;
   protected int yChange=10;
   protected int rightLeftValue;
   protected int topDownValue;
   
   protected boolean wireFrame=false;
    public void actionUp(){
    	topDownValue+=yChange;
		if(topDownValue>360){
			topDownValue-=360;
		}
    }
    public void actionDown(){
    	topDownValue-=yChange;
		if(topDownValue<0){
			topDownValue+=360;
		}
    }
    public void actionRight(){
    	rightLeftValue+=xChange;
		if(rightLeftValue>360){
			rightLeftValue-=360;
		}
    }
    public void actionCenter(){
    	rightLeftValue=0;
    	topDownValue=0;
    	wireFrame=!wireFrame;
    }
    public void actionLeft(){
    	rightLeftValue-=xChange;
		if(rightLeftValue<0){
			rightLeftValue+=360;
		}
    }

	public int getMode() {
		return mode;
	}

	public void setMode(int mode) {
		this.mode = mode;
	}

	FpsPrinter printer;
	@Override
	public void setFpsPrinter(FpsPrinter printer) {
		this.printer=printer;
	}



	@Override
	public void showFps(String fps) {
		//((Activity)mContext).setTitle(fps+" fps");
		Log.d("fps",fps+" fps");
	}
	
	
}




